﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using SplendidCRM.WCF.Data;
using System.Data;

namespace SplendidCRM.WCF
{
    // NOTE: If you change the interface name "ISplendid" here, you must also update the reference to "ISplendid" in Web.config.
    [ServiceContract]
    public interface ISplendid
    {
        /// <summary>
        /// Gets the available modules.
        /// </summary>
        /// <param name="mode">The mode to use.</param>
        /// <returns></returns>
        [OperationContract]
        List<Module> GetAvailableModules(AvilableModuleMode mode);

        /// <summary>
        /// Gets the grid view columns for a module.
        /// </summary>
        /// <param name="module">The module.</param>
        /// <returns></returns>
        [OperationContract]
        List<GridViewColumn> GetGridViewColumns(Module module);

        /// <summary>
        /// Logins the specified application name.
        /// Currently is pretty much a test method. Because this service doesnt really use sessions.
        /// </summary>
        /// <param name="applicationName">Name of the application.</param>
        /// <returns></returns>
        [OperationContract]
        LoginResults Login(string applicationName);

        /// <summary>
        /// Searches a module for the specified search term.
        /// 
        /// By default will search all columns in the ListView view.
        /// </summary>
        /// <param name="searchTerm">The search term.</param>
        /// <param name="module">The module.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="maxResults">The max results.</param>
        /// <returns></returns>
        [OperationContract]
        SearchResults Search(string searchTerm, Module module, int offset, int maxResults);

        /// <summary>
        /// Searches a module using the specified fields. Search fields can also contain just a operator such as
        /// AND or OR to create complex searches.
        /// </summary>
        /// <param name="module">The module.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="maxResults">The max results.</param>
        /// <param name="fieldsToSearch">The fields to search.</param>
        /// <returns></returns>
        [OperationContract]
        SearchResults SearchFields(Module module, int offset, int maxResults, params SearchField[] fieldsToSearch);

        /// <summary>
        /// Gets the search fields, this could be used to replicate the search pane in the CRM.
        /// 
        /// EditViewField contains type and layout information.
        /// </summary>
        /// <param name="module">The module.</param>
        /// <param name="advancedSearch">if set to <c>true</c> gets the advanced search view.</param>
        /// <returns></returns>
        [OperationContract]
        List<EditViewField> GetSearchFields(Module module, bool advancedSearch);

        /// <summary>
        /// Gets the edit fields, could be used to replicate the edit dialogue in the CRM.
        /// 
        /// EditViewField contains type and layout information.
        /// </summary>
        /// <param name="module">The module.</param>
        /// <returns></returns>
        [OperationContract]
        List<EditViewField> GetEditFields(Module module);

        /// <summary>
        /// Gets the values in a list.
        /// </summary>
        /// <param name="module">The module.</param>
        /// <param name="listName">Name of the list.</param>
        /// <returns></returns>
        [OperationContract]
        List<Terminology> GetListValues(Module module, string listName);

        /// <summary>
        /// Gets the values of any entry in a module (ie a account, contact etc).
        /// </summary>
        /// <param name="module">The module.</param>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        [OperationContract]
        Dictionary<string, string> GetEntryValues(Module module, Guid id);

        /// <summary>
        /// Updates an entry. If ID is not specified a new entry will be created.
        /// </summary>
        /// <param name="transactionId">The transaction id.</param>
        /// <param name="module">The module.</param>
        /// <param name="values">The values to update, does not need to be complete.</param>
        /// <returns></returns>
        [OperationContract]
        UpdateResults UpdateEntry(Guid transactionId, Module module, Dictionary<string, string> values);

        [OperationContract]
        UpdateResults SetNoteAttachment(Guid transactionId, NoteAttachment attachment);

        [OperationContract]
        Module GetModuleInfo(string moduleName);

        [OperationContract]
        UpdateResults AddDocumentRevision(Guid transactionId, DocumentRevision revision);

        [OperationContract]
        UpdateResults NewDocument(Guid transactionId, Document document, DocumentRevision revision);

        [OperationContract]
        UpdateResults RelateNoteToEntry(Guid transactionId, Module entryModule, Guid entryId, Guid noteId);

        [OperationContract]
        UpdateResults DeleteEntry(Guid transactionId, Module module, Guid entryId);

        [OperationContract]
        void RelateEntries(Guid transactionId, Module module1, Guid entry1Id, Module module2, Guid entry2Id);

        /// <summary>
        /// Begins a transaction.
        /// </summary>
        /// <returns></returns>
        [OperationContract]
        Guid BeginTransaction();

        /// <summary>
        /// Commits a transaction.
        /// </summary>
        /// <param name="transactionId">The transaction id.</param>
        [OperationContract]
        void CommitTransaction(Guid transactionId);

        /// <summary>
        /// Rolls back a transaction.
        /// </summary>
        /// <param name="transactionId">The transaction id.</param>
        [OperationContract]
        void RollbackTransaction(Guid transactionId);

        /// <summary>
        /// Syncs a modules entries.
        /// </summary>
        /// <param name="module">The module.</param>
        /// <param name="lastSync">The last sync time.</param>
        /// <param name="changedItems">The client side changed items.</param>
        /// <returns></returns>
        [OperationContract]
        SyncResults SyncModuleEntries(Module module, DateTime lastSync, List<Dictionary<string, string>> changedItems);
    }

    /// <summary>
    /// The mode to use when getting a list of modules.
    /// </summary>
    [DataContract]
    public enum AvilableModuleMode
    {
        /// <summary>
        /// All enabled modules
        /// </summary>
        [EnumMember]
        All,
        /// <summary>
        /// Searchable and enabled modules
        /// </summary>
        [EnumMember]
        Searchable,
        /// <summary>
        /// Relationship with notes exists and enabled
        /// </summary>
        [EnumMember]
        CanAttachNote,
        /// <summary>
        /// Relationship with emails exists and enabled
        /// </summary>
        [EnumMember]
        CanAttachEmail
    }

    [DataContract]
    public class SyncResults
    {
        private List<Dictionary<string, string>> _changedCrmItems;
        private List<Dictionary<string, string>> _conflictedItems;
        private List<Dictionary<string, string>> _createdItems;
        private List<Guid> _deletedItems;

        [DataMember]
        public List<Guid> DeletedItems
        {
            get { return _deletedItems; }
            set { _deletedItems = value; }
        }

        [DataMember]
        public List<Dictionary<string, string>> CreatedItems
        {
            get { return _createdItems; }
            set { _createdItems = value; }
        }

        [DataMember]
        public List<Dictionary<string, string>> ConflictedItems
        {
            get { return _conflictedItems; }
            set { _conflictedItems = value; }
        }

        [DataMember]
        public List<Dictionary<string, string>> ChangedCrmItems
        {
            get { return _changedCrmItems; }
            set { _changedCrmItems = value; }
        }
    }

    [DataContract]
    public class UpdateResults
    {
        private Guid _id;
        private Error _error;

        [DataMember]
        public Error Error
        {
            get { return _error; }
            set { _error = value; }
        }

        [DataMember]
        public Guid Id
        {
            get { return _id; }
            set { _id = value; }
        }
    }

    [DataContract]
    public class SearchResults
    {
        private List<Dictionary<string, string>> _results = new List<Dictionary<string, string>>();
        private List<GridViewColumn> _columns;

        [DataMember]
        public List<GridViewColumn> Columns
        {
            get { return _columns; }
            set { _columns = value; }
        }

        [DataMember]
        public List<Dictionary<string, string>> Results
        {
            get { return _results; }
            set { _results = value; }
        }
    }

    [DataContract]
    public enum Operator
    {
        Equal,
        NotEqual,
        Like,
        NotLike,
        LessThan,
        LessThanOrEqual,
        GreaterThan,
        GreaterThanOrEqual,
        OpenBracket,
        CloseBracker,
        Or,
        And,
        IsNull,
        IsNotNull
    }

    [DataContract]
    public class SearchField
    {
        private string _field;
        private string _value;
        private Operator _operator;

        [DataMember]
        public string Field
        {
            get { return _field; }
            set { _field = value; }
        }
        [DataMember]
        public string Value
        {
            get { return _value; }
            set { _value = value; }
        }

        public Operator Operator
        {
            get { return _operator; }
            set { _operator = value; }
        }
    }

    [DataContract]
    public class Error
    {
        private string _description;
        private string _name;
        private int _number;

        [DataMember]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        [DataMember]
        public int Number
        {
            get { return _number; }
            set { _number = value; }
        }

        [DataMember]
        public string Description
        {
            get { return _description; }
            set { _description = value; }
        }
    }

    [DataContract]
    public class LoginResults
    {
        private Guid _sessionId;
        private Error error;

        [DataMember]
        public Error Error
        {
            get { return error; }
            set { error = value; }
        }
        [DataMember]
        public Guid SessionId
        {
            get { return _sessionId; }
            set { _sessionId = value; }
        }
    }
}
